package miscellaneous;


import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;

import java.util.ArrayList;

import miscellaneous.Chromosome;
import miscellaneous.Gene;
import miscellaneous.Sequence;
import miscellaneous.Species;

/**
 * 
 * @author Raja Hashim Ali
 *
 */
public class SimpleFileIO {
	/*'******************************************************************************
	 * 							CLASS VARIABLES										*
	 ********************************************************************************/
	private ArrayList<Species> speciesList;
	private ArrayList<Sequence> sequences;
	
	/*'******************************************************************************
	 * 							CLASS CONSTRUCTORS									*
	 ********************************************************************************/
	public SimpleFileIO() { 
		sequences = new ArrayList<Sequence>();
		speciesList = new ArrayList<Species>();
	}
	
	/*'******************************************************************************
	 * 							CLASS PUBLIC FUNCTIONS								*
	 ********************************************************************************/
	public void readSyntenyFile(String path, String syntenyFile) throws Exception{
		String 			str;
		String[] 		strArr;
		boolean 		speciesCheck;
		boolean 		chromosomeCheck;
		BufferedReader 	bufferedreader;
		int 			count;
		
		count = 0;
		bufferedreader = new BufferedReader(new FileReader(path + syntenyFile));
		
		while ((str = bufferedreader.readLine()) != null) {
			strArr = str.split("\t");
			speciesCheck = false;
			chromosomeCheck = false;
			
			for (int i = 0; i < speciesList.size();i++) {
				if(strArr[0].equals(speciesList.get(i).getName())) {
					speciesCheck = true;
					for (int j = 0; j < speciesList.get(i).getChromosomes().size();j++) {
						if(strArr[1].equals(speciesList.get(i).getChromosomes().get(j).getChrName())) {
							chromosomeCheck = true;
							if(!strArr[3].startsWith("join")) {
								Gene gene = new Gene(strArr[2], Integer.parseInt(strArr[3]), count);
								speciesList.get(i).getChromosomes().get(j).addGene(gene);
							} else {
								strArr[3] = strArr[3].substring(5, strArr[3].indexOf(".."));
								Gene gene = new Gene(strArr[2], Integer.parseInt(strArr[3]), count);
								speciesList.get(i).getChromosomes().get(j).addGene(gene);
							}
						}
					}
					if(chromosomeCheck == false) {
						Chromosome chr = new Chromosome(strArr[1], "");
						if(!strArr[3].startsWith("join")) {
							Gene gene = new Gene(strArr[2], Integer.parseInt(strArr[3]), count);
							chr.addGene(gene);
						} else {
							strArr[3] = strArr[3].substring(5, strArr[3].indexOf(".."));
							Gene gene = new Gene(strArr[2], Integer.parseInt(strArr[3]), count);
							chr.addGene(gene);
						}
						speciesList.get(i).addChromosome(chr);
					}
				}
			}
			if(speciesCheck == false) {
				Species species = new Species(strArr[0]);
				Chromosome chr = new Chromosome(strArr[1], "");
				if(!strArr[3].startsWith("join")) {
					Gene gene = new Gene(strArr[2], Integer.parseInt(strArr[3]), count);
					chr.addGene(gene);
				} else {
					strArr[3] = strArr[3].substring(5, strArr[3].indexOf(".."));
					Gene gene = new Gene(strArr[2], Integer.parseInt(strArr[3]), count);
					chr.addGene(gene);
				}
				species.addChromosome(chr);
				speciesList.add(species);
			}
			count++;
		}
		
		for(int i = 0; i < speciesList.size(); i++) {
			for(int j = 0; j < speciesList.get(i).getChromosomes().size(); j++) 
				speciesList.get(i).getChromosomes().get(j).setGeneIndices(String.valueOf(i), String.valueOf(j));
			speciesList.get(i).setChromosomeIndices();
			speciesList.get(i).setSpeciesIndex(i);
		}
		bufferedreader.close();
	}
	
	public void readSequenceFile(String path, String fileName) throws Exception {
		String line;
		String header;
		String seq;
		boolean check;
		Sequence sequence;
		BufferedReader bufferedreader;
		
		header = "";
		seq = "";
		check = true;
		bufferedreader = new BufferedReader(new FileReader(path + fileName));
		
		while ((line = bufferedreader.readLine()) != null) {
			if(line.startsWith(">") && check == true){
				header = line.substring(1, line.length());
				check = false;
			}
			else if (line.startsWith(">") && check == false){
				sequence = new Sequence(header, seq);
				sequences.add(sequence);
				seq = "";
				header = line.substring(1, line.length());
			}
			else if(line.startsWith("\n") || line.startsWith("\r") || line.startsWith("\t") || line.startsWith(" "))
				continue;
			else 
				seq = seq.concat(line);
		}
		
		sequence = new Sequence(header, seq);
		sequences.add(sequence);
		
		bufferedreader.close();
	}
	
	public ArrayList<String> getHeaders() { 
		ArrayList<String> header = new ArrayList<String>();
		for(int i = 0; i < sequences.size(); i++) 
			header.add(sequences.get(i).getIdentifier());
		return header; 
	}
	
	public static String FileReader(String fileName) throws Exception {
		String seq;
		String line;
		BufferedReader bufferedreader;
		
		seq = "";
		bufferedreader = new BufferedReader(new FileReader(fileName));

		while ((line = bufferedreader.readLine()) != null) {
			seq	= seq.concat(line);
			seq	= seq.concat("\n");
		}
		bufferedreader.close();
		return seq;
	}
	
	public static boolean FileDeleter(String fileName){
	    boolean success = new File(fileName).delete();

	    if (!success){
	    	System.out.println("Deletion failed for file " + fileName);
	    	System.exit(-1);
	    }
		return success;
	}
	
	public ArrayList<Species> readNCFile(String path, String ncScoreFileName, ArrayList<Species> speciesList) throws Exception {	
		String 					line;
		String[] 				ncInfoArray;
		String[] 				geneIndexerArray;
		ArrayList<String> 		gene1IndexList;
		ArrayList<String> 		gene2IndexList;
		ArrayList<Float> 		ncScoreList;
		BufferedReader 			bufferedreader;

		bufferedreader = new BufferedReader(new FileReader(path + ncScoreFileName));
		gene1IndexList = new ArrayList<String>();
		gene2IndexList = new ArrayList<String>();
		ncScoreList = new ArrayList<Float>();
		
		while ((line = bufferedreader.readLine()) != null) {
			ncInfoArray = line.split(" ");
			gene1IndexList.add(ncInfoArray[0]);
			gene2IndexList.add(ncInfoArray[1]);
			ncScoreList.add(Float.parseFloat(ncInfoArray[2]));
		}
		
		for (int i = 0; i < gene1IndexList.size(); i++) {
			geneIndexerArray = gene1IndexList.get(i).split("\\.");
			speciesList.get(Integer.parseInt(geneIndexerArray[0])).getChromosomes().get(Integer.parseInt(geneIndexerArray[1])).getGeneList().get(Integer.parseInt(geneIndexerArray[2])).addncScore(gene2IndexList.get(i), ncScoreList.get(i));
		}
		return speciesList;
	}
	
	public ArrayList<Species> readEvaluationFile(String path, String evaluatedFileName, ArrayList<Species> speciesList) throws Exception {	
		String 					line;
		String[] 				ncInfoArray;
		String[] 				geneIndexerArray;
		ArrayList<String> 		gene1IndexList;
		ArrayList<String> 		gene2IndexList;
		ArrayList<Float> 		ncScoreList;
		BufferedReader 			bufferedreader;

		bufferedreader = new BufferedReader(new FileReader(path + evaluatedFileName));
		gene1IndexList = new ArrayList<String>();
		gene2IndexList = new ArrayList<String>();
		ncScoreList = new ArrayList<Float>();
		
		while ((line = bufferedreader.readLine()) != null) {
			ncInfoArray = line.split("\t");
			gene1IndexList.add(ncInfoArray[0]);
			gene2IndexList.add(ncInfoArray[1]);
			ncScoreList.add(Float.parseFloat(ncInfoArray[2]));
		}
		
		for (int i = 0; i < gene1IndexList.size(); i++) {
			geneIndexerArray = gene1IndexList.get(i).split("\\.");
			speciesList.get(Integer.parseInt(geneIndexerArray[0])).getChromosomes().get(Integer.parseInt(geneIndexerArray[1])).getGeneList().get(Integer.parseInt(geneIndexerArray[2])).addncScore(gene2IndexList.get(i), ncScoreList.get(i));
		}
		return speciesList;
	}

	public ArrayList<Species> readNCandSyntenyFile(String path, String ncAndSySFileName, ArrayList<Species> speciesList) throws Exception {	
		String 					line;
		String[] 				ncInfoArray;
		String[] 				geneIndexerArray;
		ArrayList<String> 		gene1IndexList;
		ArrayList<String> 		gene2IndexList;
		ArrayList<Float> 		ncScoreList;
		ArrayList<Float> 		syntenyScoreList;
		BufferedReader 			bufferedreader;

		bufferedreader = new BufferedReader(new FileReader(path + ncAndSySFileName));
		gene1IndexList = new ArrayList<String>();
		gene2IndexList = new ArrayList<String>();
		ncScoreList = new ArrayList<Float>();
		syntenyScoreList = new ArrayList<Float>();
		
		
		while ((line = bufferedreader.readLine()) != null) {
			ncInfoArray = line.split("\t");
			gene1IndexList.add(ncInfoArray[0]);
			gene2IndexList.add(ncInfoArray[1]);
			ncScoreList.add(Float.parseFloat(ncInfoArray[2]));
			syntenyScoreList.add(Float.parseFloat(ncInfoArray[3]));
		}
		
		for (int i = 0; i < gene1IndexList.size(); i++) {
			geneIndexerArray = gene1IndexList.get(i).split("\\.");
			speciesList.get(Integer.parseInt(geneIndexerArray[0])).getChromosomes().get(Integer.parseInt(geneIndexerArray[1])).getGeneList().get(Integer.parseInt(geneIndexerArray[2])).addncScore(gene2IndexList.get(i), ncScoreList.get(i));
			speciesList.get(Integer.parseInt(geneIndexerArray[0])).getChromosomes().get(Integer.parseInt(geneIndexerArray[1])).getGeneList().get(Integer.parseInt(geneIndexerArray[2])).addSyntenyScore(syntenyScoreList.get(i));
		}
		return speciesList;
	}
	
	public ArrayList<Species> readBlastFile(String path, String blastFileName, ArrayList<Species> speciesList) throws Exception {	
		String 					line;
		String[]				strArr;
		String[]				strArr1;
		BufferedReader 			bufferedreader;
		
		bufferedreader = new BufferedReader(new FileReader(path + blastFileName));
		while ((line = bufferedreader.readLine()) != null) {
			strArr = line.split(" ");
			strArr1 = strArr[0].split("\\.");
			speciesList.get(Integer.parseInt(strArr1[0])).getChromosomes().get(Integer.parseInt(strArr1[1])).getGeneList().get(Integer.parseInt(strArr1[2])).addBlastResult(strArr[1], Float.parseFloat(strArr[2]));
		}
		return speciesList;
	}
	
	public int getNumberOfGenes() {
		int count = 0;
		for(int i = 0; i < speciesList.size(); i++)
			for(int j = 0; j < speciesList.get(i).getChromosomes().size(); j++)
				count = count + speciesList.get(i).getChromosomes().get(j).getGeneList().size();
		return count;
	}
	
	public ArrayList<Sequence> getSequences() { return sequences; }
	public void emptySequences() { sequences = null; }
	public ArrayList<Species> getSpeciesList() { return speciesList; }
	public int getNumberofSpecies() { return speciesList.size(); }
		
	/*'******************************************************************************
	 * 							END OF CLASS										*
	 ********************************************************************************/
}
